﻿using System;
using System.Net;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Documents;
using System.Windows.Ink;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Shapes;
using System.Windows.Automation.Peers;
using System.Globalization;

namespace System.Windows.BidiControls
{
    public class DatePicker : System.Windows.Controls.DatePicker
    {
        private System.Windows.Controls.Calendar _calendar;
        private FrameworkElement _root;
        private System.Windows.Controls.Primitives.Popup _popUp;
        private Canvas _outsideCanvas;
        private Canvas _outsidePopupCanvas;
        private System.Windows.Controls.Primitives.DatePickerTextBox _textBox;

        public DatePicker()
        {
            DefaultStyleKey = typeof(System.Windows.Controls.DatePicker);
            this.CalendarOpened += new RoutedEventHandler(DatePicker_CalendarOpened);
        }

        void DatePicker_CalendarOpened(object sender, RoutedEventArgs e)
        {
            //System.Windows.Automation.Peers.CalendarAutomationPeer _calendarPeer = new System.Windows.Automation.Peers.CalendarAutomationPeer(_calendar);
            //System.Collections.Generic.List<Automation.Peers.AutomationPeer> peers = _calendarPeer.GetChildren();

            //foreach (AutomationPeer p in peers)
            //{
            //    FrameworkElementAutomationPeer elP = p as FrameworkElementAutomationPeer;
            //    if (elP.Owner is StackPanel)
            //        System.Diagnostics.Debug.WriteLine("yeeeha");
            //}
            
            //System.Windows.Controls.Primitives.DatePickerTextBox _dt;
            //object o = _calendar.FindName("Root");
            //object rootVisual = getRootVisual(_calendar);
            //System.Collections.Generic.IEnumerable<UIElement> elements =  VisualTreeHelper.FindElementsInHostCoordinates(_calendar.TransformToVisual(null).Transform(new Point(5, 0)), rootVisual as UIElement);
            //foreach (UIElement el in elements)
            //{
            //    if (el is System.Windows.Controls.Primitives.DatePickerTextBox)
            //        _dt = el as System.Windows.Controls.Primitives.DatePickerTextBox;
            //}
            //int count = VisualTreeHelper.GetChildrenCount(this._calendar);
        }

        private object getRootVisual(FrameworkElement el)
        {
            if (el.Parent != null)
                return getRootVisual(el.Parent as FrameworkElement);
            return el;
        }

        public override void OnApplyTemplate()
        {
            base.OnApplyTemplate();
            this._root = base.GetTemplateChild("Root") as FrameworkElement;
            this._popUp = base.GetTemplateChild("Popup") as System.Windows.Controls.Primitives.Popup;
            this._outsideCanvas = _popUp.Child as System.Windows.Controls.Canvas;
            this._outsidePopupCanvas = _outsideCanvas.Children[0] as Canvas;
            this._calendar = _outsideCanvas.Children[1] as System.Windows.Controls.Calendar;
            this._textBox = base.GetTemplateChild("TextBox") as System.Windows.Controls.Primitives.DatePickerTextBox;
            _outsideCanvas.Children.RemoveAt(1);
            this.InitializeCalendar();
            _outsideCanvas.Children.Add(this._calendar);
        }

        private void InitializeCalendar()
        {
            this._calendar = new System.Windows.BidiControls.Calendar();
            //this._calendar.DayButtonMouseUp += new MouseButtonEventHandler(this.Calendar_DayButtonMouseUp);
            this._calendar.DisplayDateChanged += new EventHandler<CalendarDateChangedEventArgs>(this.Calendar_DisplayDateChanged);
            this._calendar.SelectedDatesChanged += new EventHandler<SelectionChangedEventArgs>(this.Calendar_SelectedDatesChanged);
            this._calendar.MouseLeftButtonDown += new MouseButtonEventHandler(this.Calendar_MouseLeftButtonDown);
            this._calendar.KeyDown += new KeyEventHandler(this.Calendar_KeyDown);
            this._calendar.SelectionMode = CalendarSelectionMode.SingleDate;
            this._calendar.SizeChanged += new SizeChangedEventHandler(this.Calendar_SizeChanged);
            this._calendar.IsTabStop = true;
        }

        private void Calendar_DisplayDateChanged(object sender, CalendarDateChangedEventArgs e)
        {
            if (e.AddedDate != this.DisplayDate)
            {
                base.SetValue(DisplayDateProperty, e.AddedDate.Value);
            }
        }

        private void Calendar_SelectedDatesChanged(object sender, SelectionChangedEventArgs e)
        {
            if (((e.AddedItems.Count > 0) && this.SelectedDate.HasValue) && (DateTime.Compare((DateTime)e.AddedItems[0], this.SelectedDate.Value) != 0))
            {
                this.SelectedDate = (DateTime?)e.AddedItems[0];
            }
            else if (e.AddedItems.Count == 0)
            {
                this.SelectedDate = null;
            }
            else if (!this.SelectedDate.HasValue && (e.AddedItems.Count > 0))
            {
                this.SelectedDate = (DateTime?)e.AddedItems[0];
            }
            this.setTextBox();
            base.Focus();
            this.IsDropDownOpen = false;
            this._calendar.ReleaseMouseCapture();
        }

        private void setTextBox()
        {
            string _textValue = "";
            System.Globalization.DateTimeFormatInfo currentDateFormat = new System.Globalization.CultureInfo(System.Globalization.CultureInfo.InvariantCulture.Name).DateTimeFormat;
            DateTime d = this.SelectedDate.Value;
            switch (this.SelectedDateFormat)
            {
                case DatePickerFormat.Long:
                    _textValue = string.Format(CultureInfo.CurrentCulture, d.ToString(currentDateFormat.LongDatePattern, currentDateFormat), new object[0]);
                    break;

                case DatePickerFormat.Short:
                    _textValue = string.Format(CultureInfo.CurrentCulture, d.ToString(currentDateFormat.ShortDatePattern, currentDateFormat), new object[0]);
                    break;
            }
            this._textBox.Text = _textValue; 
        }

        private void Calendar_MouseLeftButtonDown(object sender, MouseButtonEventArgs e)
        {
            e.Handled = true;
        }

        private void Calendar_KeyDown(object sender, KeyEventArgs e)
        {
            System.Windows.Controls.Calendar calendar = sender as System.Windows.Controls.Calendar;
            if ((!e.Handled && (((e.Key == Key.Enter) || (e.Key == Key.Space)) || (e.Key == Key.Escape))) && (calendar.DisplayMode == CalendarMode.Month))
            {
                base.Focus();
                this.IsDropDownOpen = false;
            }
        }

        private void Calendar_SizeChanged(object sender, SizeChangedEventArgs e)
        {
            this.SetPopUpPosition();
        }

        private void SetPopUpPosition()
        {
            if (((this._calendar != null) && (Application.Current != null)) && ((Application.Current.Host != null) && (Application.Current.Host.Content != null)))
            {
                double actualHeight = Application.Current.Host.Content.ActualHeight;
                double actualWidth = Application.Current.Host.Content.ActualWidth;
                double num3 = this._calendar.ActualHeight;
                double num4 = base.ActualHeight;
                if (this._root != null)
                {
                    MatrixTransform transform = this._root.TransformToVisual(null) as MatrixTransform;
                    if (transform != null)
                    {
                        double offsetX = transform.Matrix.OffsetX;
                        double offsetY = transform.Matrix.OffsetY;
                        double num7 = offsetX;
                        double num8 = offsetY + num4;
                        if (actualHeight < (num8 + num3))
                        {
                            num8 = offsetY - num3;
                        }
                        this._popUp.HorizontalOffset = 0.0;
                        this._popUp.VerticalOffset = 0.0;
                        this._outsidePopupCanvas.Width = actualWidth;
                        this._outsidePopupCanvas.Height = actualHeight;
                        this._calendar.HorizontalAlignment = HorizontalAlignment.Left;
                        this._calendar.VerticalAlignment = VerticalAlignment.Top;
                        Canvas.SetLeft(this._calendar, num7 - offsetX);
                        Canvas.SetTop(this._calendar, num8 - offsetY);
                        Matrix matrix = transform.Matrix;
                        if (InvertMatrix(ref matrix))
                        {
                            transform.Matrix = matrix;
                            this._outsidePopupCanvas.RenderTransform = transform;
                        }
                    }
                }
            }
        }

        private static bool InvertMatrix(ref Matrix matrix)
        {
            double num = (matrix.M11 * matrix.M22) - (matrix.M12 * matrix.M21);
            if (num == 0.0)
            {
                return false;
            }
            Matrix matrix2 = matrix;
            matrix.M11 = matrix2.M22 / num;
            matrix.M12 = (-1.0 * matrix2.M12) / num;
            matrix.M21 = (-1.0 * matrix2.M21) / num;
            matrix.M22 = matrix2.M11 / num;
            matrix.OffsetX = ((matrix2.OffsetY * matrix2.M21) - (matrix2.OffsetX * matrix2.M22)) / num;
            matrix.OffsetY = ((matrix2.OffsetX * matrix2.M12) - (matrix2.OffsetY * matrix2.M11)) / num;
            return true;
        }
    }
}
